﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace DimensionsHelper.SourceGeneration.Constants
{

    public class ConstantFieldGenerationInfo
    {

        public ConstantFieldGenerationInfo(ConstantFieldGenerationInfoList list)
        {
            List = list;
        }


        /// <summary>
        /// 字段所在的列表
        /// </summary>
        public ConstantFieldGenerationInfoList List { get; }


        /// <summary>
        /// 属性或字段名称
        /// </summary>
        public string FieldName { get; set; }


        /// <summary>
        /// 属性或字段的值，当字段或属性可以获取常量值，此属性存储常量，
        /// 否则，此属性是属性全名，用以传递属性值。
        /// </summary>
        public string FieldValue { get; set; }


        /// <summary>
        /// 属性或字段的类型全名
        /// </summary>
        public string FieldTypeFullName { get; set; }


        /// <summary>
        /// 生成的目标属性名
        /// </summary>
        public string TargetPropertyName { get; set; }


        /// <summary>
        /// 资源类自带的注释
        /// </summary>
        public string Comment { get; set; }

    }


    public class ConstantFieldGenerationInfoList : IEnumerable<ConstantFieldGenerationInfo>
    {

        /// <summary>
        /// 命名空间名
        /// </summary>
        public string Namespace { get; set; }


        /// <summary>
        /// 生成的类型名
        /// </summary>
        public string ClassName { get; set; }


        /// <summary>
        /// 资源类类型名
        /// </summary>
        public string ResourceClassName { get; set; }


        /// <summary>
        /// 获取或设置创建目标对象使用的方法名。
        /// </summary>
        public string Creator { get; set; }


        /// <summary>
        /// 目标类型全名
        /// </summary>
        public string TargetTypeFullName { get; set; }


        /// <summary>
        /// 目标类型的生成信息
        /// </summary>
        public ObjectInfo TargetTypeInfo { get; set; }



        private readonly List<ConstantFieldGenerationInfo> fields = new List<ConstantFieldGenerationInfo>();


        /// <summary>
        /// 获取字段列表的长度
        /// </summary>
        public int Count => fields.Count;


        /// <summary>
        /// 向末尾追加一个新的字段信息
        /// </summary>
        /// <param name="targetName">生成的目标属性名</param>
        /// <param name="fieldName">字段或属性名</param>
        /// <param name="fieldValue">字段或属性值</param>
        /// <param name="fieldTypeFullName">字段或属性的类型全名</param>
        public void Add(string targetName, string fieldName, string fieldValue, string fieldTypeFullName, string comment = null)
        {
            fields.Add(new ConstantFieldGenerationInfo(this) 
            { 
                TargetPropertyName = targetName,
                FieldName = fieldName, 
                FieldValue = fieldValue,
                FieldTypeFullName = fieldTypeFullName,
                Comment = comment,
            });
        }


        /// <summary>
        /// 如果标注的类型带有<see langword="static"/>关键字，设置此属性为<see langword="true"/>
        /// </summary>
        public bool IsStatic { get; set; }


        /// <summary>
        /// 如果标注的类型带有<see langword="internal"/>关键字，设置此属性为<see langword="true"/>
        /// </summary>
        public bool IsInternal { get; set; }


        public IEnumerator<ConstantFieldGenerationInfo> GetEnumerator()
        {
            return fields.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }



    public class ObjectMemberInfo
    {

        /// <summary>
        /// 成员绑定的匹配表达式
        /// </summary>
        public Regex Mather { get; set; }


        /// <summary>
        /// 如果此成员需要定义的常量值，将此属性设置为<see langword="true"/>。
        /// </summary>
        public bool IsConstantValue { get; set; }


        /// <summary>
        /// 如果值类型是枚举类型，将此属性设置为<see langword="true"/>。
        /// </summary>
        public bool IsEnum { get; set; }


        /// <summary>
        /// 如果此成员类型是值类型，将此属性设置为<see langword="true"/>。
        /// </summary>
        public bool IsValueType { get; set; }


        /// <summary>
        /// 成员的类型全名
        /// </summary>
        public string TypeFullName { get; set; }


        /// <summary>
        /// 成员属性、字段或参数的名称
        /// </summary>
        public string Name { get; set; }


        /// <summary>
        /// 如果成员属性带有 required 修饰符并且不带有两种特性，将此属性设置为<see langword="true"/>。
        /// </summary>
        public bool IsRequiredDefault { get; set; }


        public string ToSyntax(string sourceFieldName, string sourceFieldValue)
        {
            if (IsRequiredDefault)
            {
                return IsValueType ? "default" : "null";
            }

            if (IsConstantValue)
            {
                return sourceFieldValue;
            }

            if (Mather != null)
            {
                var match = Mather.Match(sourceFieldName);
                var res = new StringBuilder();

                if (match.Success)
                {
                    if (IsEnum)
                    {
                        res.Append(TypeFullName).Append('.').Append(match.Value);
                    }
                    // 字符串
                    else if (TypeFullName == "string")
                    {
                        res.Append('"').Append(match.Value).Append('"');
                    }
                    // 字符
                    else if (TypeFullName == "char")
                    {
                        res.Append('\'').Append(match.Value).Append('\'');
                    }
                    else
                    {
                        res.Append(match.Value);
                    }
                }

                return res.ToString();
            }

            return string.Empty;
        }

    }



    /// <summary>
    /// 根据常量属性或字段生成的目标对象的属性信息。
    /// </summary>
    public class ObjectInfo
    {

        /// <summary>
        /// 类型全名
        /// </summary>
        public string TypeFullName { get; set; }


        /// <summary>
        /// 成员列表
        /// </summary>
        public List<ObjectMemberInfo> Members { get; set; }


        /// <summary>
        /// 如果存储的信息是构造函数，将此属性设置为<see langword="true"/>。
        /// </summary>
        public bool IsConstructor { get; set; }



        /// <summary>
        /// 将指定的字段名和字段值转换为对象初始化表达式。
        /// <list type="bullet">
        ///     <item><term>对于构造函数</term><code>new TypeName(Arg1, Arg2)</code></item>
        ///     <item><term>对于非构造函数</term><code>new TypeName 
        /// {
        ///     Property1 = Value1,
        ///     Property2 = Value2,
        /// }</code></item>
        /// </list>
        /// </summary>
        /// <remarks>
        /// 最后不带分号
        /// </remarks>
        public string ToSyntax(string sourceFieldName, string sourceFieldValue)
        {
            var builder = new StringBuilder();
            builder.Append("new ").Append(TypeFullName);

            if (IsConstructor)
            {
                builder.Append('(');

                for (int i = 0; i < Members.Count; i++)
                {
                    if (i > 0)
                    {
                        builder.Append(", ");
                    }

                    builder.Append(Members[i].ToSyntax(sourceFieldName, sourceFieldValue));
                }

                builder.Append(')');
            }
            else
            {
                builder.AppendLine();
                builder.AppendLine("{");

                foreach (var member in Members)
                {
                    builder.Append("    ")
                           .Append(member.Name)
                           .Append(" = ")
                           .Append(member.ToSyntax(sourceFieldName, sourceFieldValue))
                           .Append(',')
                           .AppendLine();
                }

                builder.Append('}');
            }

            return builder.ToString();
        }


    }



}
